/**
  ******************************************************************************
  * @file    usart.c
  * @author  TONLY
  * @version V1.0
  * @date    2022-01-01
  * @brief   串口
  ******************************************************************************
  * @attention
  * 
  *	本程序只供学习使用，未经作者许可，不得用于其它任何用途
  *	版权所有，盗版必究
  *
  * <h2><center>&copy; COPYRIGHT 2022 华清-TONLY </center></h2>
  ******************************************************************************
  */   

/* Includes ------------------------------------------------------------------*/
#include "usart.h"
#include <stdarg.h>

//发生中断
#if	USART1_USE_NVIC||USART2_USE_NVIC||USART3_USE_NVIC||UART4_USE_NVIC||UART5_USE_NVIC
	#include "stmnvic.h"
#endif


#if SYSTEM_USE_PRINTF

#include <stdio.h>
#pragma import(__use_no_semihosting) 	//避免使用半主机函数

//标准库需要支持的函数
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;    

//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 

//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while(USART_GetFlagStatus(PRINTF_USART,USART_FLAG_TXE)==RESET){}
	USART_SendData(PRINTF_USART,(uint8_t)ch);
	while(USART_GetFlagStatus(PRINTF_USART,USART_FLAG_TC)==RESET){} 
	return ch;
}

#endif /* SYSTEM_USE_PRINTF */


#if	SYSTEM_USE_USART1	/* 如果使用USART1 */

/* Public functions ----------------------------------------------------------*/
/**
  * @brief  串口初始化
  * @param  bound : 波特率
  * @retval None
  */
void USART1_Init(u32 bound)
{
	static u8 isUSART1Init;
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;

	if(isUSART1Init)
		return;
	
	//开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	/* 配置TX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin 		= GPIO_Pin_9;
	GPIO_InitStruct.GPIO_Speed 		= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/* 配置RX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin 		= GPIO_Pin_10;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/* 中断配置 */
	#if USART1_USE_NVIC
		STMNVIC_Init();
		STMNVIC_Config(USART1_IRQn,1,1);
		USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//接受数据产生中断
		USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);
	#endif
	
	//串口配置
	USART_InitStruct.USART_BaudRate				= bound;
	USART_InitStruct.USART_HardwareFlowControl	= USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode					= USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStruct.USART_Parity				= USART_Parity_No;
	USART_InitStruct.USART_StopBits				= USART_StopBits_1;
	USART_InitStruct.USART_WordLength			= USART_WordLength_8b;
	USART_Init(USART1,&USART_InitStruct);
	USART_Cmd(USART1,ENABLE);
	
	isUSART1Init = 1;
}

#endif /* SYSTEM_USE_USART1 */


#if	SYSTEM_USE_USART2	/* 如果使用USART2 */

/* Public functions ----------------------------------------------------------*/
/**
  * @brief  串口初始化
  * @param  bound : 波特率
  * @retval None
  */
void USART2_Init(u32 bound)
{
	static u8 isUSART2Init;
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	
	if(isUSART2Init)
		return;
	
	//开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	
	/* 配置TX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin  		= GPIO_Pin_2;
	GPIO_InitStruct.GPIO_Speed 		= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/* 配置RX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin 		= GPIO_Pin_3;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/* 中断配置 */
	#if USART2_USE_NVIC
		STMNVIC_Init();
		STMNVIC_Config(USART2_IRQn,1,1);
		USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//接受数据产生中断
		USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);//空闲产生中断
	#endif
	
	//串口配置
	USART_InitStruct.USART_BaudRate				= bound;
	USART_InitStruct.USART_HardwareFlowControl	= USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode					= USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStruct.USART_Parity				= USART_Parity_No;
	USART_InitStruct.USART_StopBits				= USART_StopBits_1;
	USART_InitStruct.USART_WordLength			= USART_WordLength_8b;
	USART_Init(USART2,&USART_InitStruct);
	USART_Cmd(USART2,ENABLE);
	
	isUSART2Init = 1;
}

#endif /* SYSTEM_USE_USART2 */


#if	SYSTEM_USE_USART3	/* 如果使用USART3 */

/* Public functions ----------------------------------------------------------*/
/**
  * @brief  串口初始化
  * @param  bound : 波特率
  * @retval None
  */
void USART3_Init(u32 bound)
{
	static u8 isUSART3Init;
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	
	if(isUSART3Init)
		return;
	
	//开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
	
	/* 配置TX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin 		  = GPIO_Pin_10;
	GPIO_InitStruct.GPIO_Speed 		= GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	/* 配置RX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin 		= GPIO_Pin_11;
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	/* 中断配置 */
	#if USART3_USE_NVIC
		STMNVIC_Init();
		STMNVIC_Config(USART3_IRQn,1,1);
		USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//接受数据产生中断
		USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);//空闲产生中断
	#endif
	
	//串口配置
	USART_InitStruct.USART_BaudRate				= bound;
	USART_InitStruct.USART_HardwareFlowControl	= USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode					= USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStruct.USART_Parity				= USART_Parity_No;
	USART_InitStruct.USART_StopBits				= USART_StopBits_1;
	USART_InitStruct.USART_WordLength			= USART_WordLength_8b;
	USART_Init(USART3,&USART_InitStruct);
	USART_Cmd(USART3,ENABLE);
	
	isUSART3Init = 1;
}

#endif /* SYSTEM_USE_USART3 */


#if	SYSTEM_USE_UART4	/* 如果使用UART4 */

/* Public functions ----------------------------------------------------------*/
/**
  * @brief  串口初始化
  * @param  bound : 波特率
  * @retval None
  */
void UART4_Init(u32 bound)
{
	static u8 isUART4Init;
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	
	if(isUART4Init)
		return;
	
	//开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
	
	/* 配置TX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin 		= GPIO_Pin_10;
	GPIO_InitStruct.GPIO_Speed 		= GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStruct);
	
	/* 配置RX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin 		= GPIO_Pin_11;
	GPIO_Init(GPIOC,&GPIO_InitStruct);
	
	/* 中断配置 */
	#if UART4_USE_NVIC
		STMNVIC_Init();
		STMNVIC_Config(UART4_IRQn,1,1);
		USART_ITConfig(UART4,USART_IT_RXNE,ENABLE);//接受数据产生中断
		USART_ITConfig(UART4,USART_IT_IDLE,ENABLE);//空闲产生中断
	#endif
	
	//串口配置
	USART_InitStruct.USART_BaudRate				= bound;
	USART_InitStruct.USART_HardwareFlowControl	= USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode					= USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStruct.USART_Parity				= USART_Parity_No;
	USART_InitStruct.USART_StopBits				= USART_StopBits_1;
	USART_InitStruct.USART_WordLength			= USART_WordLength_8b;
	USART_Init(UART4,&USART_InitStruct);
	USART_Cmd(UART4,ENABLE);
	
	isUART4Init= 1;
}

#endif /* SYSTEM_USE_UART4 */


#if	SYSTEM_USE_UART5	/* 如果使用UART5 */

/* Public functions ----------------------------------------------------------*/
/**
  * @brief  串口初始化
  * @param  bound : 波特率
  * @retval None
  */
void UART5_Init(u32 bound)
{
	static u8 isUART5Init;
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef USART_InitStruct;
	
	if(isUART5Init)
		return;
	
	//开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);
	
	/* 配置TX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin 		= GPIO_Pin_12;
	GPIO_InitStruct.GPIO_Speed 		= GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStruct);
	
	/* 配置RX */
	GPIO_InitStruct.GPIO_Mode 		= GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin 		= GPIO_Pin_2;
	GPIO_Init(GPIOD,&GPIO_InitStruct);
	
	/* 中断配置 */
	#if UART5_USE_NVIC
		STMNVIC_Init();
		STMNVIC_Config(UART5_IRQn,1,1);
		USART_ITConfig(UART5,USART_IT_RXNE,ENABLE);//接受数据产生中断
		USART_ITConfig(UART5,USART_IT_IDLE,ENABLE);//空闲产生中断
	#endif
	
	//串口配置
	USART_InitStruct.USART_BaudRate				= bound;
	USART_InitStruct.USART_HardwareFlowControl	= USART_HardwareFlowControl_None;
	USART_InitStruct.USART_Mode					= USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStruct.USART_Parity				= USART_Parity_No;
	USART_InitStruct.USART_StopBits				= USART_StopBits_1;
	USART_InitStruct.USART_WordLength			= USART_WordLength_8b;
	USART_Init(UART5,&USART_InitStruct);
	USART_Cmd(UART5,ENABLE);
	
	isUART5Init = 1;
}

#endif /* SYSTEM_USE_UART5 */


/**
  * @brief  串口发送n个字节
  * @param  USARTx ：串口（USART1 USART2 USART3 UART4 UART5）
  * @param  ch     ：数据首地址
  * @retval None
  */
void USART_Send_NByte(USART_TypeDef* USARTx,u8 *ch,u32 size)
{
	u32 i;
	for(i=0;i<size;i++){
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
		USART_SendData(USARTx,ch[i]);
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
	}
}

/**
  * @brief  串口发送字符串
  * @param  USARTx ：串口（USART1 USART2 USART3 UART4 UART5）
  * @param  ch     ：数据首地址
  * @retval None
  */
void USART_Send_String(USART_TypeDef* USARTx,char *ch)
{
	while(*ch!='\0'){
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
		USART_SendData(USARTx,*ch);
		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
		ch++;
	}
}


static char *itoa( int value, char *string, int radix )
{
    int     i, d;
    int     flag = 0;
    char    *ptr = string;

    /* This implementation only works for decimal numbers. */
    if (radix != 10)
    {
        *ptr = 0;
        return string;
    }

    if (!value)
    {
        *ptr++ = 0x30;
        *ptr = 0;
        return string;
    }

    /* if this is a negative value insert the minus sign. */
    if (value < 0)
    {
        *ptr++ = '-';

        /* Make the value positive. */
        value *= -1;

    }

    for (i = 10000; i > 0; i /= 10)
    {
        d = value / i;

        if (d || flag)
        {
            *ptr++ = (char)(d + 0x30);
            value -= (d * i);
            flag = 1;
        }
    }

    /* Null terminate the string. */
    *ptr = 0;

    return string;

} /* NCL_Itoa */


void USART_printf ( USART_TypeDef * USARTx, char * Data, ... )
{
    const char *s;
    int d;   
    char buf[16];


    va_list ap;
    va_start(ap, Data);

    while ( * Data != 0 )     // 判断数据是否到达结束符
    {                                         
        if ( * Data == 0x5c )  //'\'
        {                                     
            switch ( *++Data )
            {
                case 'r':                                     //回车符
                USART_SendData(USARTx, 0x0d);
                Data ++;
                break;

                case 'n':                                     //换行符
                USART_SendData(USARTx, 0x0a);   
                Data ++;
                break;

                default:
                Data ++;
                break;
            }            
        }

        else if ( * Data == '%')
        {                                     
            switch ( *++Data )
            {               
                case 's':                                         //字符串
                s = va_arg(ap, const char *);
                for ( ; *s; s++) 
                {
                    USART_SendData(USARTx,*s);
                    while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
                }
                Data++;
                break;

                case 'd':           
                    //十进制
                d = va_arg(ap, int);
                itoa(d, buf, 10);
                for (s = buf; *s; s++) 
                {
                    USART_SendData(USARTx,*s);
                    while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
                }
                     Data++;
                     break;
                default:
                     Data++;
                     break;
            }        
        }
        else USART_SendData(USARTx, *Data++);
        while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );

    }
}

void PrintComBit(USART_TypeDef* USARTx, uint8_t Data)
{ 
			USART_SendData(USARTx, Data);    /*发送单个数据 */
			while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);/* 检查指定的USART标志位即RESET＝1时发送完成*/													
}




/******************* (C) COPYRIGHT 2022 华清-TONLY *************END OF FILE****/
